using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Reflection;
using System.Text.Json;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Configuration;

/// <summary>
/// 增强版应用设置映射器
/// 提供强类型配置绑定、验证、缓存和监控功能
/// </summary>
public class EnhancedAppSettingsMapper
{
    private readonly IConfiguration _configuration;
    private readonly ILogger<EnhancedAppSettingsMapper>? _logger;
    private readonly ConcurrentDictionary<string, object> _cache;
    private readonly ConcurrentDictionary<string, DateTime> _cacheTimestamps;
    private readonly TimeSpan _cacheTimeout;

    public EnhancedAppSettingsMapper(IConfiguration configuration, ILogger<EnhancedAppSettingsMapper>? logger = null)
    {
        _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        _logger = logger;
        _cache = new ConcurrentDictionary<string, object>();
        _cacheTimestamps = new ConcurrentDictionary<string, DateTime>();
        _cacheTimeout = TimeSpan.FromMinutes(30); // 默认缓存30分钟
    }

    /// <summary>
    /// 绑定配置到指定类型（根级别）
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <returns>配置对象实例</returns>
    public T BindRoot<T>() where T : class, new()
    {
        return Bind<T>(string.Empty);
    }

    /// <summary>
    /// 绑定指定节的配置到指定类型
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="sectionKey">配置节键</param>
    /// <returns>配置对象实例</returns>
    public T Bind<T>(string sectionKey) where T : class, new()
    {
        var cacheKey = $"{typeof(T).FullName}_{sectionKey}";
        
        // 检查缓存
        if (TryGetFromCache<T>(cacheKey, out var cachedValue))
        {
            _logger?.LogTrace("Configuration retrieved from cache for key: {CacheKey}", cacheKey);
            return cachedValue;
        }

        try
        {
            var instance = new T();
            var configSection = string.IsNullOrEmpty(sectionKey) ? _configuration : _configuration.GetSection(sectionKey);
            
            // 使用 Microsoft 的配置绑定
            configSection.Bind(instance);
            
            // 执行数据验证
            ValidateConfiguration(instance, sectionKey);
            
            // 缓存结果
            _cache.TryAdd(cacheKey, instance);
            _cacheTimestamps.TryAdd(cacheKey, DateTime.UtcNow);
            
            _logger?.LogDebug("Configuration bound and cached for type {TypeName}, section: {SectionKey}", 
                typeof(T).Name, sectionKey ?? "root");
            
            return instance;
        }
        catch (Exception ex)
        {
            _logger?.LogError(ex, "Failed to bind configuration for type {TypeName}, section: {SectionKey}", 
                typeof(T).Name, sectionKey ?? "root");
            throw new InvalidOperationException(
                $"Failed to bind configuration for type {typeof(T).Name} from section '{sectionKey ?? "root"}': {ex.Message}", 
                ex);
        }
    }

    /// <summary>
    /// 获取配置值
    /// </summary>
    /// <typeparam name="T">值类型</typeparam>
    /// <param name="key">配置键</param>
    /// <param name="defaultValue">默认值</param>
    /// <returns>配置值</returns>
    public T GetValue<T>(string key, T defaultValue = default!)
    {
        try
        {
            var value = _configuration.GetValue<T>(key, defaultValue);
            _logger?.LogTrace("Retrieved configuration value for key {Key}: {Value}", key, value);
            return value == null ? defaultValue : value;
        }
        catch (Exception ex)
        {
            _logger?.LogWarning(ex, "Failed to retrieve configuration value for key {Key}, using default: {DefaultValue}", 
                key, defaultValue);
            return defaultValue;
        }
    }

    /// <summary>
    /// 获取配置节
    /// </summary>
    /// <param name="key">配置节键</param>
    /// <returns>配置节</returns>
    public IConfigurationSection GetSection(string key)
    {
        return _configuration.GetSection(key);
    }

    /// <summary>
    /// 检查配置键是否存在
    /// </summary>
    /// <param name="key">配置键</param>
    /// <returns>是否存在</returns>
    public bool Exists(string key)
    {
        return _configuration.GetSection(key).Exists();
    }

    /// <summary>
    /// 获取所有配置键值对（扁平化）
    /// </summary>
    /// <returns>配置字典</returns>
    public IDictionary<string, string?> GetAllConfiguration()
    {
        var cacheKey = "all_configuration";
        
        if (TryGetFromCache<Dictionary<string, string?>>(cacheKey, out var cachedDict))
        {
            return cachedDict;
        }

        try
        {
            var result = new Dictionary<string, string?>();
            FlattenConfiguration(_configuration, result, string.Empty);
            
            // 缓存结果
            _cache.TryAdd(cacheKey, result);
            _cacheTimestamps.TryAdd(cacheKey, DateTime.UtcNow);
            
            _logger?.LogDebug("Retrieved all configuration with {Count} items", result.Count);
            return result;
        }
        catch (Exception ex)
        {
            _logger?.LogError(ex, "Failed to retrieve all configuration");
            throw;
        }
    }

    /// <summary>
    /// 获取连接字符串
    /// </summary>
    /// <param name="name">连接字符串名称</param>
    /// <returns>连接字符串</returns>
    public string? GetConnectionString(string name)
    {
        var connectionString = _configuration.GetConnectionString(name);
        _logger?.LogTrace("Retrieved connection string for {Name}: {HasValue}", name, !string.IsNullOrEmpty(connectionString));
        return connectionString;
    }

    /// <summary>
    /// 绑定配置到现有对象实例
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="instance">现有实例</param>
    /// <param name="sectionKey">配置节键</param>
    public void BindTo<T>(T instance, string sectionKey = "") where T : class
    {
        try
        {
            var configSection = string.IsNullOrEmpty(sectionKey) ? _configuration : _configuration.GetSection(sectionKey);
            configSection.Bind(instance);
            
            ValidateConfiguration(instance, sectionKey);
            
            _logger?.LogDebug("Configuration bound to existing instance of type {TypeName}, section: {SectionKey}", 
                typeof(T).Name, sectionKey ?? "root");
        }
        catch (Exception ex)
        {
            _logger?.LogError(ex, "Failed to bind configuration to existing instance of type {TypeName}, section: {SectionKey}", 
                typeof(T).Name, sectionKey ?? "root");
            throw;
        }
    }

    /// <summary>
    /// 监听配置变化
    /// </summary>
    /// <param name="callback">变化回调</param>
    /// <returns>变化令牌</returns>
    public IDisposable OnConfigurationChanged(Action<IConfiguration> callback)
    {
        return _configuration.GetReloadToken().RegisterChangeCallback(state =>
        {
            ClearCache();
            callback(_configuration);
            _logger?.LogInformation("Configuration changed, cache cleared");
        }, null);
    }

    /// <summary>
    /// 清除缓存
    /// </summary>
    public void ClearCache()
    {
        var cacheCount = _cache.Count;
        _cache.Clear();
        _cacheTimestamps.Clear();
        _logger?.LogDebug("Configuration cache cleared, {Count} items removed", cacheCount);
    }

    /// <summary>
    /// 清除过期缓存
    /// </summary>
    public void ClearExpiredCache()
    {
        var now = DateTime.UtcNow;
        var expiredKeys = _cacheTimestamps
            .Where(kvp => now - kvp.Value > _cacheTimeout)
            .Select(kvp => kvp.Key)
            .ToList();

        foreach (var key in expiredKeys)
        {
            _cache.TryRemove(key, out _);
            _cacheTimestamps.TryRemove(key, out _);
        }

        if (expiredKeys.Count > 0)
        {
            _logger?.LogDebug("Removed {Count} expired cache entries", expiredKeys.Count);
        }
    }

    /// <summary>
    /// 获取缓存统计信息
    /// </summary>
    /// <returns>缓存统计</returns>
    public ConfigurationCacheStats GetCacheStats()
    {
        ClearExpiredCache(); // 清理过期缓存后再统计
        
        return new ConfigurationCacheStats
        {
            TotalItems = _cache.Count,
            OldestItem = _cacheTimestamps.Values.Min(),
            NewestItem = _cacheTimestamps.Values.Max(),
            CacheTimeout = _cacheTimeout
        };
    }

    #region 私有辅助方法

    /// <summary>
    /// 尝试从缓存获取值
    /// </summary>
    private bool TryGetFromCache<T>(string cacheKey, out T value) where T : class
    {
        value = default!;
        
        if (!_cache.TryGetValue(cacheKey, out var cachedObj) || 
            !_cacheTimestamps.TryGetValue(cacheKey, out var timestamp))
        {
            return false;
        }

        // 检查是否过期
        if (DateTime.UtcNow - timestamp > _cacheTimeout)
        {
            _cache.TryRemove(cacheKey, out _);
            _cacheTimestamps.TryRemove(cacheKey, out _);
            return false;
        }

        if (cachedObj is T typedValue)
        {
            value = typedValue;
            return true;
        }

        return false;
    }

    /// <summary>
    /// 验证配置对象
    /// </summary>
    private void ValidateConfiguration<T>(T instance, string sectionKey) where T : class
    {
        var validationContext = new ValidationContext(instance)
        {
            DisplayName = $"{typeof(T).Name} configuration"
        };

        var validationResults = new List<ValidationResult>();
        
        if (!Validator.TryValidateObject(instance, validationContext, validationResults, validateAllProperties: true))
        {
            var errors = validationResults.Select(vr => vr.ErrorMessage).ToList();
            var errorMessage = $"Configuration validation failed for section '{sectionKey ?? "root"}': {string.Join("; ", errors)}";
            
            _logger?.LogError("Configuration validation failed for {TypeName}: {Errors}", 
                typeof(T).Name, string.Join("; ", errors));
            
            throw new ValidationException(errorMessage);
        }
    }

    /// <summary>
    /// 扁平化配置
    /// </summary>
    private static void FlattenConfiguration(IConfiguration config, IDictionary<string, string?> result, string prefix)
    {
        foreach (var section in config.GetChildren())
        {
            var key = string.IsNullOrEmpty(prefix) ? section.Key : $"{prefix}:{section.Key}";
            
            if (section.Value != null)
            {
                result[key] = section.Value;
            }
            else
            {
                FlattenConfiguration(section, result, key);
            }
        }
    }

    #endregion
}

/// <summary>
/// 配置缓存统计信息
/// </summary>
public class ConfigurationCacheStats
{
    /// <summary>
    /// 缓存项总数
    /// </summary>
    public int TotalItems { get; set; }

    /// <summary>
    /// 最旧的缓存项时间
    /// </summary>
    public DateTime OldestItem { get; set; }

    /// <summary>
    /// 最新的缓存项时间
    /// </summary>
    public DateTime NewestItem { get; set; }

    /// <summary>
    /// 缓存超时时间
    /// </summary>
    public TimeSpan CacheTimeout { get; set; }

    /// <summary>
    /// 缓存命中率（需要外部跟踪）
    /// </summary>
    public double HitRate { get; set; }
}
